#############################################################################################
#############################################################################################
# 
#   Open Source License/Disclaimer, Forecast Systems Laboratory NOAA/OAR/GSD, 
#   325 Broadway Boulder, CO 80305
#
#   This software is distributed under the Open Source Definition, which may be 
#   found at http://www.opensource.org/.
#   In particular, redistribution and use in source and binary forms, with or 
#   without modification, are permitted provided that the following conditions are met:
#
#   - Redistributions of source code must retain this notice, this list of 
#     conditions and the following disclaimer.
#
#   - Redistributions in binary form must provide access to this notice, this 
#     list of conditions and the following disclaimer, and the underlying source code.
#
#   - All modifications to this software must be clearly documented, and are 
#     solely the responsibility of the agent making the modifications.
#
#   - If significant modifications or enhancements are made to this software, 
#     the GSD Software Policy Manager (softwaremgr.fsl@noaa.gov) should be notified.
#
#   THIS SOFTWARE AND ITS DOCUMENTATION ARE IN THE PUBLIC DOMAIN AND ARE 
#   FURNISHED "AS IS." THE AUTHORS, THE UNITED STATES GOVERNMENT, ITS INSTRUMENTALITIES,
#   OFFICERS, EMPLOYEES, AND AGENTS MAKE NO WARRANTY, EXPRESS OR IMPLIED, AS TO
#   THE USEFULNESS OF THE SOFTWARE AND DOCUMENTATION FOR ANY PURPOSE. THEY ASSUME 
#   NO RESPONSIBILITY (1) FOR THE USE OF THE SOFTWARE AND DOCUMENTATION; OR (2) TO PROVIDE
#   TECHNICAL SUPPORT TO USERS. 
#############################################################################################
#############################################################################################


import inspect
import numpy as np

class EnsembleGeneratorClass(object):
    # This serves as a template for the user of cdar to implement
    # their own ensemble generation. It usually calls some simulation
    # routine provided by the user. The initial conditions and
    # parameters used in the ensemble generation are contained in one
    # array. Hence the initialization conditions are treated as
    # parameters.

    def __init__(self):
        # Initialization just defines the object and this will be used
        # by the data assimilation function in the
        # DataAssimilationClass.
        self.Name = 'Ensemble Name'

    # Returns the ensemble array propagated forward from the
    # initialization and parametrization in Param. 
    # EnsArray = (Ntimestep*SimulationDimension)x(EnSize) numpy array    
    def fwd_propagate(self,Param,start_time,stop_time,Ntimestep):
        # For an example implementation look at
        # SIRensemble.py.

        # Initialization includes the parameter array, start time, stop time, and the number of timesteps
        # Param = (param size + initialization size)x(Ensemble Size) numpy array
        # start_time, stop_time = float
        # Ntimestep = integer
        self.Param = Param
        self.start_time = start_time
        self.stop_time = stop_time
        self.Ntimestep = Ntimestep
        self.EnSize = Param.shape[1]
        self.EnsTime = np.linspace(start_time,stop_time,Ntimestep)

        # Usually a function is to be called a number of times equal
        # to self.EnSize corresponding to the different
        # initializations/parametrizations in self.ParamArray. The
        # simulation is then run from self.start_time to
        # self.stop_time for a number of timesteps equal to
        # self.Ntimestep. Regardless of the shape of the array
        # returned by the simulation each simulation output is turned
        # into a column vector of succesive time points and inserted
        # into a column of EnsArray. This is then attached to the
        # EnsembleGeneratorClass object using self.EnsArray =
        # EnsArray.
        raise NotImplementedError(inspect.stack()[0][3])
